@@ -228,3 +228,7 @@ h2 .scenario, a span.label.scenario { |
||
228 | 228 |
display: none; |
229 | 229 |
} |
230 | 230 |
} |
231 |
+ |
|
232 |
+.confirm-agent .popover { |
|
233 |
+ width: 200px; |
|
234 |
+} |
@@ -22,7 +22,7 @@ class Agent < ActiveRecord::Base |
||
22 | 22 |
|
23 | 23 |
EVENT_RETENTION_SCHEDULES = [["Forever", 0], ["1 day", 1], *([2, 3, 4, 5, 7, 14, 21, 30, 45, 90, 180, 365].map {|n| ["#{n} days", n] })] |
24 | 24 |
|
25 |
- attr_accessible :options, :memory, :name, :type, :schedule, :controller_ids, :control_target_ids, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately |
|
25 |
+ attr_accessible :options, :memory, :name, :type, :schedule, :controller_ids, :control_target_ids, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately, :drop_pending_events |
|
26 | 26 |
|
27 | 27 |
json_serialize :options, :memory |
28 | 28 |
|
@@ -196,6 +196,14 @@ class Agent < ActiveRecord::Base |
||
196 | 196 |
update_column :last_error_log_at, nil |
197 | 197 |
end |
198 | 198 |
|
199 |
+ def drop_pending_events |
|
200 |
+ false |
|
201 |
+ end |
|
202 |
+ |
|
203 |
+ def drop_pending_events=(bool) |
|
204 |
+ set_last_checked_event_id if bool |
|
205 |
+ end |
|
206 |
+ |
|
199 | 207 |
# Callbacks |
200 | 208 |
|
201 | 209 |
def set_default_schedule |
@@ -207,7 +215,7 @@ class Agent < ActiveRecord::Base |
||
207 | 215 |
end |
208 | 216 |
|
209 | 217 |
def set_last_checked_event_id |
210 |
- if newest_event_id = Event.order("id desc").limit(1).pluck(:id).first |
|
218 |
+ if can_receive_events? && newest_event_id = Event.maximum(:id) |
|
211 | 219 |
self.last_checked_event_id = newest_event_id |
212 | 220 |
end |
213 | 221 |
end |
@@ -20,10 +20,12 @@ |
||
20 | 20 |
</li> |
21 | 21 |
|
22 | 22 |
<li> |
23 |
- <% if agent.disabled? %> |
|
24 |
- <%= link_to '<i class="glyphicon glyphicon-play"></i> Enable agent'.html_safe, agent_path(agent, :agent => { :disabled => false }, :return => returnTo), :method => :put %> |
|
25 |
- <% else %> |
|
26 |
- <%= link_to '<i class="glyphicon glyphicon-pause"></i> Disable agent'.html_safe, agent_path(agent, :agent => { :disabled => true }, :return => returnTo), :method => :put %> |
|
23 |
+ <%= link_to '#', 'data-toggle' => 'modal', 'data-target' => "#confirm-agent#{agent.id}" do %> |
|
24 |
+ <% if agent.disabled? %> |
|
25 |
+ <i class="glyphicon glyphicon-play"></i> Enable agent |
|
26 |
+ <% else %> |
|
27 |
+ <i class="glyphicon glyphicon-pause"></i> Disable agent |
|
28 |
+ <% end %> |
|
27 | 29 |
<% end %> |
28 | 30 |
</li> |
29 | 31 |
|
@@ -49,3 +51,32 @@ |
||
49 | 51 |
<%= link_to '<span class="color-danger glyphicon glyphicon-remove"></span> Delete agent'.html_safe, agent_path(agent, :return => returnTo), method: :delete, data: { confirm: 'Are you sure that you want to permanently delete this Agent?' }, :tabindex => "-1" %> |
50 | 52 |
</li> |
51 | 53 |
</ul> |
54 |
+ |
|
55 |
+<div id="confirm-agent<%= agent.id %>" class="confirm-agent modal fade" tabindex="-1" role="dialog" aria-labelledby="confirmAgentLabel" aria-hidden="true"> |
|
56 |
+ <div class="modal-dialog modal-sm"> |
|
57 |
+ <div class="modal-content"> |
|
58 |
+ <div class="modal-header"> |
|
59 |
+ <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> |
|
60 |
+ <h4 class="modal-title">Confirm</h4> |
|
61 |
+ </div> |
|
62 |
+ <div class="modal-body"> |
|
63 |
+ <p><% if agent.disabled? %>Enable<% else %>Disable<% end %> "<%= agent.name %>"?</p> |
|
64 |
+ </div> |
|
65 |
+ <div class="modal-footer"> |
|
66 |
+ <%= form_for(agent, as: :agent, url: agent_path(agent, return: returnTo), method: 'PUT') do |f| %> |
|
67 |
+ <% if agent.disabled && agent.can_receive_events? %> |
|
68 |
+ <div class="form-group"> |
|
69 |
+ <%= f.check_box :drop_pending_events %> |
|
70 |
+ <%= f.label :drop_pending_events, 'Drop pending events' %> |
|
71 |
+ <span class="glyphicon glyphicon-question-sign hover-help" data-content="As soon as you enable this agent, it starts to receive pending events that have not been processed while it was disabled. To prevent that from happening, you can check this option."></span> |
|
72 |
+ </div> |
|
73 |
+ <% end %> |
|
74 |
+ <%= f.hidden_field :disabled, value: (!agent.disabled).to_s %> |
|
75 |
+ <%= f.button 'No', class: 'btn btn-default', 'data-dismiss' => 'modal' %> |
|
76 |
+ <%= f.submit 'Yes', class: 'btn btn-primary' %> |
|
77 |
+ <% end %> |
|
78 |
+ </div> |
|
79 |
+ </div> |
|
80 |
+ </div> |
|
81 |
+</div> |
|
82 |
+ |
@@ -251,6 +251,18 @@ describe AgentsController do |
||
251 | 251 |
response.should redirect_to(agents_path) |
252 | 252 |
end |
253 | 253 |
end |
254 |
+ |
|
255 |
+ it "updates last_checked_event_id when drop_pending_events is given" do |
|
256 |
+ sign_in users(:bob) |
|
257 |
+ agent = agents(:bob_website_agent) |
|
258 |
+ agent.disabled = true |
|
259 |
+ agent.last_checked_event_id = nil |
|
260 |
+ agent.save! |
|
261 |
+ post :update, id: agents(:bob_website_agent).to_param, agent: { disabled: 'false', drop_pending_events: 'true' } |
|
262 |
+ agent.reload |
|
263 |
+ agent.disabled.should == false |
|
264 |
+ agent.last_checked_event_id.should == Event.maximum(:id) |
|
265 |
+ end |
|
254 | 266 |
end |
255 | 267 |
|
256 | 268 |
describe "PUT leave_scenario" do |
@@ -757,6 +757,59 @@ describe Agent do |
||
757 | 757 |
end |
758 | 758 |
end |
759 | 759 |
end |
760 |
+ |
|
761 |
+ describe '.last_checked_event_id' do |
|
762 |
+ it "should be updated by setting drop_pending_events to true" do |
|
763 |
+ agent = agents(:bob_rain_notifier_agent) |
|
764 |
+ agent.last_checked_event_id = nil |
|
765 |
+ agent.save! |
|
766 |
+ agent.update!(drop_pending_events: true) |
|
767 |
+ agent.reload.last_checked_event_id.should == Event.maximum(:id) |
|
768 |
+ end |
|
769 |
+ |
|
770 |
+ it "should not affect a virtual attribute drop_pending_events" do |
|
771 |
+ agent = agents(:bob_rain_notifier_agent) |
|
772 |
+ agent.update!(drop_pending_events: true) |
|
773 |
+ agent.reload.drop_pending_events.should == false |
|
774 |
+ end |
|
775 |
+ end |
|
776 |
+ |
|
777 |
+ describe ".drop_pending_events" do |
|
778 |
+ before do |
|
779 |
+ stub_request(:any, /wunderground/).to_return(body: File.read(Rails.root.join("spec/data_fixtures/weather.json")), status: 200) |
|
780 |
+ stub.any_instance_of(Agents::WeatherAgent).is_tomorrow?(anything) { true } |
|
781 |
+ end |
|
782 |
+ |
|
783 |
+ it "should drop pending events while the agent was disabled when set to true" do |
|
784 |
+ agent1 = agents(:bob_weather_agent) |
|
785 |
+ agent2 = agents(:bob_rain_notifier_agent) |
|
786 |
+ |
|
787 |
+ -> { |
|
788 |
+ -> { |
|
789 |
+ Agent.async_check(agent1.id) |
|
790 |
+ Agent.receive! |
|
791 |
+ }.should change { agent1.events.count }.by(1) |
|
792 |
+ }.should change { agent2.events.count }.by(1) |
|
793 |
+ |
|
794 |
+ agent2.disabled = true |
|
795 |
+ agent2.save! |
|
796 |
+ |
|
797 |
+ -> { |
|
798 |
+ -> { |
|
799 |
+ Agent.async_check(agent1.id) |
|
800 |
+ Agent.receive! |
|
801 |
+ }.should change { agent1.events.count }.by(1) |
|
802 |
+ }.should_not change { agent2.events.count } |
|
803 |
+ |
|
804 |
+ agent2.disabled = false |
|
805 |
+ agent2.drop_pending_events = true |
|
806 |
+ agent2.save! |
|
807 |
+ |
|
808 |
+ -> { |
|
809 |
+ Agent.receive! |
|
810 |
+ }.should_not change { agent2.events.count } |
|
811 |
+ end |
|
812 |
+ end |
|
760 | 813 |
end |
761 | 814 |
|
762 | 815 |
describe AgentDrop do |